﻿namespace VolleyballHall
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;

    public static class ModelCreator
    {
        public static List<VertexPositionNormalTexture> GetCuboid(Vector3 size, Vector3 d, float dir)
        {
            size.X /= 2.0f;
            size.Y /= 2.0f;
            size.Z /= 2.0f;

            var topLeftFront = new Vector3(-size.X + d.X, size.Y + d.Y, size.Z + d.Z);
            var bottomLeftFront = new Vector3(-size.X + d.X, -size.Y + d.Y, size.Z + d.Z);
            var topRightFront = new Vector3(size.X + d.X, size.Y + d.Y, size.Z + d.Z);
            var bottomRightFront = new Vector3(size.X + d.X, -size.Y + d.Y, size.Z + d.Z);
            var topLeftBack = new Vector3(-size.X + d.X, size.Y + d.Y, -size.Z + d.Z);
            var topRightBack = new Vector3(size.X + d.X, size.Y + d.Y, -size.Z + d.Z);
            var bottomLeftBack = new Vector3(-size.X + d.X, -size.Y + d.Y, -size.Z + d.Z);
            var bottomRightBack = new Vector3(size.X + d.X, -size.Y + d.Y, -size.Z + d.Z);

            var frontNormal = new Vector3(0.0f, 0.0f, dir);
            var backNormal = new Vector3(0.0f, 0.0f, -dir);
            var topNormal = new Vector3(0.0f, dir, 0.0f);
            var bottomNormal = new Vector3(0.0f, -dir, 0.0f);
            var leftNormal = new Vector3(-dir, 0.0f, 0.0f);
            var rightNormal = new Vector3(dir, 0.0f, 0.0f);

            var cubeVertices = new VertexPositionNormalTexture[36];

            var textureTopLeft = new Vector2(0.0f, 0.0f);
            var textureTopRight = new Vector2(1.0f, 0.0f);
            var textureBottomLeft = new Vector2(0.0f, 1.0f);
            var textureBottomRight = new Vector2(1.0f, 1.0f);

            // Front face.
            cubeVertices[0] =
                new VertexPositionNormalTexture(
                topLeftFront, frontNormal, textureTopLeft);
            cubeVertices[1] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            cubeVertices[2] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);
            cubeVertices[3] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            cubeVertices[4] =
                new VertexPositionNormalTexture(
                bottomRightFront, frontNormal, textureBottomRight);
            cubeVertices[5] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);

            // Back face.
            cubeVertices[6] =
                new VertexPositionNormalTexture(
                topLeftBack, backNormal, textureTopRight);
            cubeVertices[7] =
                new VertexPositionNormalTexture(
                topRightBack, backNormal, textureTopLeft);
            cubeVertices[8] =
                new VertexPositionNormalTexture(
                bottomLeftBack, backNormal, textureBottomRight);
            cubeVertices[9] =
                new VertexPositionNormalTexture(
                bottomLeftBack, backNormal, textureBottomRight);
            cubeVertices[10] =
                new VertexPositionNormalTexture(
                topRightBack, backNormal, textureTopLeft);
            cubeVertices[11] =
                new VertexPositionNormalTexture(
                bottomRightBack, backNormal, textureBottomLeft);

            // Top face.
            cubeVertices[12] =
                new VertexPositionNormalTexture(
                topLeftFront, topNormal, textureBottomLeft);
            cubeVertices[13] =
                new VertexPositionNormalTexture(
                topRightBack, topNormal, textureTopRight);
            cubeVertices[14] =
                new VertexPositionNormalTexture(
                topLeftBack, topNormal, textureTopLeft);
            cubeVertices[15] =
                new VertexPositionNormalTexture(
                topLeftFront, topNormal, textureBottomLeft);
            cubeVertices[16] =
                new VertexPositionNormalTexture(
                topRightFront, topNormal, textureBottomRight);
            cubeVertices[17] =
                new VertexPositionNormalTexture(
                topRightBack, topNormal, textureTopRight);

            // Bottom face. 
            cubeVertices[18] =
                new VertexPositionNormalTexture(
                bottomLeftFront, bottomNormal, textureTopLeft);
            cubeVertices[19] =
                new VertexPositionNormalTexture(
                bottomLeftBack, bottomNormal, textureBottomLeft);
            cubeVertices[20] =
                new VertexPositionNormalTexture(
                bottomRightBack, bottomNormal, textureBottomRight);
            cubeVertices[21] =
                new VertexPositionNormalTexture(
                bottomLeftFront, bottomNormal, textureTopLeft);
            cubeVertices[22] =
                new VertexPositionNormalTexture(
                bottomRightBack, bottomNormal, textureBottomRight);
            cubeVertices[23] =
                new VertexPositionNormalTexture(
                bottomRightFront, bottomNormal, textureTopRight);

            // Left face.
            cubeVertices[24] =
                new VertexPositionNormalTexture(
                topLeftFront, leftNormal, textureTopRight);
            cubeVertices[25] =
                new VertexPositionNormalTexture(
                bottomLeftBack, leftNormal, textureBottomLeft);
            cubeVertices[26] =
                new VertexPositionNormalTexture(
                bottomLeftFront, leftNormal, textureBottomRight);
            cubeVertices[27] =
                new VertexPositionNormalTexture(
                topLeftBack, leftNormal, textureTopLeft);
            cubeVertices[28] =
                new VertexPositionNormalTexture(
                bottomLeftBack, leftNormal, textureBottomLeft);
            cubeVertices[29] =
                new VertexPositionNormalTexture(
                topLeftFront, leftNormal, textureTopRight);

            // Right face. 
            cubeVertices[30] =
                new VertexPositionNormalTexture(
                topRightFront, rightNormal, textureTopLeft);
            cubeVertices[31] =
                new VertexPositionNormalTexture(
                bottomRightFront, rightNormal, textureBottomLeft);
            cubeVertices[32] =
                new VertexPositionNormalTexture(
                bottomRightBack, rightNormal, textureBottomRight);
            cubeVertices[33] =
                new VertexPositionNormalTexture(
                topRightBack, rightNormal, textureTopRight);
            cubeVertices[34] =
                new VertexPositionNormalTexture(
                topRightFront, rightNormal, textureTopLeft);
            cubeVertices[35] =
                new VertexPositionNormalTexture(
                bottomRightBack, rightNormal, textureBottomRight);

            
 
            return cubeVertices.ToList();
        }

        public static List<VertexPositionNormalTexture> GetRectangle(Vector2 size)
        {


            var topLeftFront = new Vector3(0, 0, 0);
            var bottomLeftFront = new Vector3(0, size.Y, 0);
            var topRightFront = new Vector3(size.X, 0, 0);
            var bottomRightFront = new Vector3(size.X, size.Y, 0);


            var frontNormal = new Vector3(0.0f, 0.0f, 1);


            var rectangleVertices = new VertexPositionNormalTexture[6];

            var textureTopLeft = new Vector2(0.0f, 0.0f);
            var textureTopRight = new Vector2(0.0f, 1.0f);
            var textureBottomLeft = new Vector2(1.0f, 0.0f);
            var textureBottomRight = new Vector2(1.0f, 1.0f);

            // Front face.
            rectangleVertices[0] =
                new VertexPositionNormalTexture(
                topLeftFront, frontNormal, textureTopLeft);
            rectangleVertices[1] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            rectangleVertices[2] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);
            rectangleVertices[3] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            rectangleVertices[4] =
                new VertexPositionNormalTexture(
                bottomRightFront, frontNormal, textureBottomRight);
            rectangleVertices[5] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);

            return rectangleVertices.ToList();
        }

        public static List<VertexPositionNormalTexture> GetRectangle(Vector3 x1, Vector3 x2, Vector3 y1, Vector3 y2, Vector3 normal)
        {
            var topLeftFront = x1;
            var bottomLeftFront = y1;
            var topRightFront = y2;
            var bottomRightFront = x2;


            var frontNormal = normal;


            var rectangleVertices = new VertexPositionNormalTexture[6];

            var textureTopLeft = new Vector2(0.0f, 0.0f);
            var textureTopRight = new Vector2(0.0f, 1.0f);
            var textureBottomLeft = new Vector2(1.0f, 0.0f);
            var textureBottomRight = new Vector2(1.0f, 1.0f);

            // Front face.
            rectangleVertices[0] =
                new VertexPositionNormalTexture(
                topLeftFront, frontNormal, textureTopLeft);
            rectangleVertices[1] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            rectangleVertices[2] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);
            rectangleVertices[3] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            rectangleVertices[4] =
                new VertexPositionNormalTexture(
                bottomRightFront, frontNormal, textureBottomRight);
            rectangleVertices[5] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);

            return rectangleVertices.ToList();
        }

        public static List<VertexPositionNormalTexture> GetSphere(Vector3 d, float r)
        {
            const int I = 15;
            const int J = 15;
            const float DAlpha = MathHelper.TwoPi / I;
            const float DBeta = MathHelper.Pi / J;



            var sphereVertices = new List<VertexPositionNormalTexture>();

            for (int i = 0; i < I; i++)
                for (int j = 0; j < J; j++)
                {
                    var x = (float)(Math.Sin(DAlpha * i) * Math.Sin(DBeta * j) * r);
                    var y = (float)(Math.Cos(DAlpha * i) * Math.Sin(DBeta * j) * r);
                    var z = (float)(Math.Cos(DBeta * j) * r);

                    var normal = new Vector3(x, y, z);
                    normal.Normalize();

                    var text = Vector2.Zero;

                    sphereVertices.Add(new VertexPositionNormalTexture
                                           (new Vector3(x + d.X, y + +d.Y, z + d.Z), normal, text));

                    x = (float)(Math.Sin(DAlpha * (i + 1)) * Math.Sin(DBeta * j) * r);
                    y = (float)(Math.Cos(DAlpha * (i + 1)) * Math.Sin(DBeta * j) * r);
                    z = (float)(Math.Cos(DBeta * j) * r);
                    normal = new Vector3(x, y, z);
                    normal.Normalize();
                    sphereVertices.Add(new VertexPositionNormalTexture
                                           (new Vector3(x + d.X, y + +d.Y, z + d.Z), normal, text));

                    x = (float)(Math.Sin(DAlpha * i) * Math.Sin(DBeta * (j + 1)) * r);
                    y = (float)(Math.Cos(DAlpha * i) * Math.Sin(DBeta * (j + 1)) * r);
                    z = (float)(Math.Cos(DBeta * (j + 1)) * r);
                    normal = new Vector3(x, y, z);
                    normal.Normalize();
                    sphereVertices.Add(new VertexPositionNormalTexture
                                           (new Vector3(x + d.X, y + +d.Y, z + d.Z), normal, text));
                    x = (float)(Math.Sin(DAlpha * (i + 1)) * Math.Sin(DBeta * j) * r);
                    y = (float)(Math.Cos(DAlpha * (i + 1)) * Math.Sin(DBeta * j) * r);
                    z = (float)(Math.Cos(DBeta * j) * r);
                    normal = new Vector3(x, y, z);
                    normal.Normalize();
                    sphereVertices.Add(new VertexPositionNormalTexture
                                           (new Vector3(x + d.X, y + +d.Y, z + d.Z), normal, text));

                    x = (float)(Math.Sin(DAlpha * i) * Math.Sin(DBeta * (j + 1)) * r);
                    y = (float)(Math.Cos(DAlpha * i) * Math.Sin(DBeta * (j + 1)) * r);
                    z = (float)(Math.Cos(DBeta * (j + 1)) * r);
                    normal = new Vector3(x, y, z);
                    normal.Normalize();
                    sphereVertices.Add(new VertexPositionNormalTexture
                                           (new Vector3(x + d.X, y + +d.Y, z + d.Z), normal, text));

                    x = (float)(Math.Sin(DAlpha * (i + 1)) * Math.Sin(DBeta * (j + 1)) * r);
                    y = (float)(Math.Cos(DAlpha * (i + 1)) * Math.Sin(DBeta * (j + 1)) * r);
                    z = (float)(Math.Cos(DBeta * (j + 1)) * r);
                    normal = new Vector3(x, y, z);
                    normal.Normalize();
                    sphereVertices.Add(new VertexPositionNormalTexture
                                           (new Vector3(x + d.X, y + +d.Y, z + d.Z), normal, text));


                }

            return sphereVertices;
        }
        public static List<VertexPositionNormalTexture> GetCylinder(float r, float h, Vector3 d)
        {

            const int I = 50;
            const float DAlpha = MathHelper.TwoPi / I;

            var cylinderVertices = new List<VertexPositionNormalTexture>();

            for (int i = 0; i < I; i++)
            {
                var x = (float)(Math.Sin(DAlpha * i) * r);
                var y = (float)(Math.Cos(DAlpha * i) * r);
                var z = 0.0f;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(x, y, 0), Vector2.Zero));

                x = (float)(Math.Sin(DAlpha * (i + 1)) * r);
                y = (float)(Math.Cos(DAlpha * (i + 1)) * r);
                z = 0.0f;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(x, y, 0), Vector2.Zero));

                x = (float)(Math.Sin(DAlpha * i) * r);
                y = (float)(Math.Cos(DAlpha * i) * r);
                z = h;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(x, y, 0), Vector2.Zero));
                x = (float)(Math.Sin(DAlpha * (i + 1)) * r);
                y = (float)(Math.Cos(DAlpha * (i + 1)) * r);
                z = 0.0f;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(x, y, 0), Vector2.Zero));

                x = (float)(Math.Sin(DAlpha * i) * r);
                y = (float)(Math.Cos(DAlpha * i) * r);
                z = h;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(x, y, 0), Vector2.Zero));

                x = (float)(Math.Sin(DAlpha * (i + 1)) * r);
                y = (float)(Math.Cos(DAlpha * (i + 1)) * r);
                z = h;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(x, y, 0), Vector2.Zero));



                x = (float)(Math.Sin(DAlpha * i) * r);
                y = (float)(Math.Cos(DAlpha * i) * r);
                z = h;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(0, 0, 1), Vector2.Zero));

                x = (float)(Math.Sin(DAlpha * (i + 1)) * r);
                y = (float)(Math.Cos(DAlpha * (i + 1)) * r);
                z = h;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z), new Vector3(0, 0, 1), Vector2.Zero));
                x = 0f;
                y = 0f;
                z = h;
                cylinderVertices.Add(new VertexPositionNormalTexture
                        (new Vector3(x + d.X, y + +d.Y, z + d.Z),  new Vector3(0, 0, 1), Vector2.Zero));



            }



            return cylinderVertices;
        }

        public static List<VertexPositionNormalTexture> GetNet()
        {

            var netVertices = new List<VertexPositionNormalTexture>();


            netVertices.AddRange(GetCuboid(new Vector3(1, 100, 10), 20f * Vector3.UnitZ, 1));
            netVertices.AddRange(GetCylinder(1, 25, -50 * Vector3.UnitY));
            netVertices.AddRange(GetCylinder(1, 25, 50 * Vector3.UnitY));
            return netVertices;

         }

        public static List<VertexPositionNormalTexture> GetBench()
        {

            var benchVertices = new List<VertexPositionNormalTexture>();


            benchVertices.AddRange(GetCuboid(new Vector3(10, 4, 1), 2.5f * Vector3.UnitZ, 1));
            benchVertices.AddRange(GetCylinder(1, 2, -3 * Vector3.UnitX));
            benchVertices.AddRange(GetCylinder(1, 2, 3 * Vector3.UnitX));
            return benchVertices;
        }


        public static void PrepareLamp(Model lampModel, Effect effect)
        {
            foreach (ModelMeshPart meshPart in lampModel.Meshes[0].MeshParts)
            {
                int size = meshPart.VertexBuffer.VertexCount;
                var data = new VertexPositionNormalTexture[size];
                meshPart.VertexBuffer.GetData(data);
                var list = new List<VertexPositionNormalTexture>(data);

                data = list.TransformPositionNormalBy( Matrix.CreateScale(2) * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateTranslation(30, 80, -23.5f) ).ToArray();
                meshPart.VertexBuffer.SetData(data);

                meshPart.Effect = effect;
            }


        }

        public static void PrepareHuman(Model humanModel, Effect effect)
        {
            foreach (ModelMeshPart meshPart in humanModel.Meshes[0].MeshParts)
            {
                int size = meshPart.VertexBuffer.VertexCount;
                var data = new VertexPositionNormalTexture[size];
                meshPart.VertexBuffer.GetData(data);
                var list = new List<VertexPositionNormalTexture>(data);
                data = list.TransformPositionNormalBy(Matrix.CreateScale(1 / 12.0f) * Matrix.CreateRotationX(MathHelper.PiOver2) * Matrix.CreateRotationZ(-MathHelper.PiOver2 - MathHelper.PiOver4) * Matrix.CreateTranslation(-25, 80, -30f)).ToArray();
                meshPart.VertexBuffer.SetData(data);

                meshPart.Effect = effect;
            }


        }



    }
}
